package com.tomorrow.payments_hodgepodge.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tomorrow.payments_hodgepodge.service.ARBService;
import com.tomorrow.payments_hodgepodge.util.ARBUtil;
import com.tomorrow.payments_hodgepodge.util.CommonResult;
import com.tomorrow.payments_hodgepodge.util.HttpsUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;

/**
 * @author Tomorrow
 * @date 2020/11/3 17:41
 */
@Service
@Slf4j
public class ARBServiceImpl implements ARBService {
    @Value("${project.ARB.KEY}")
    public String key;
    @Value("${project.ARB.PASSWORD}")
    public String password;
    @Value("${project.ARB.TRANPORTA_ID}")
    public String tranportalId;
    @Value("${project.ARB.BANK_HOSTED_URL}")
    public String BANK_HOSTED_URL;
    @Value("${project.ARB.MERCHANT_HOSTED_URL}")
    public String MERCHANT_HOSTED_URL;
    @Value("${project.ARB.CALLBACK}")
    public String callback;

    @Override
    public CommonResult createOrder(String orderNo) {
        JSONObject jsonObject = new JSONObject();
        // 跨门户ID。商家下载相同的商家门户网站
        jsonObject.put("id", tranportalId);
        // 支付网关发送的商家成功URL 通知请求。
        jsonObject.put("responseURL", callback);
        // 支付网关发送的商家错误URL 在处理事务时发生任何错误时响应。
        jsonObject.put("errorURL", callback);

        JSONObject requestParams = new JSONObject();
        // 交易金额
        requestParams.put("amt", "12.00");
        // 定义事务操作 采购:1 退款:2 无效:3 调查:8
        requestParams.put("action", "1");
        // Tranportal密码。在商家门户下载相同的商家。
        requestParams.put("password", password);
        // 跨门户ID。商家下载相同的商家门户网站
        requestParams.put("id", tranportalId);
        // KSA的3位货币代码例:682
        requestParams.put("currencyCode", "682");
        // 商户唯一参考编号
        requestParams.put("trackId", orderNo);
        // 用户(商家)定义这些字段。现场数据为 与事务请求一起传递，然后返回 在事务响应中。商户应确保 字段在不需要传递数据时留空。
        requestParams.put("udf1", "udf1text");
//        requestParams.put("udf2", "udf2text");
//        requestParams.put("udf3", "udf3text");
//        requestParams.put("udf4", "udf4text");
//        requestParams.put("udf5", "udf5text");
        // 支付网关发送的商家成功URL 通知请求。
        requestParams.put("responseURL", callback);
        // 支付网关发送的商家错误URL 在处理事务时发生任何错误时响应。
        requestParams.put("errorURL", callback);

//        JSONObject accountDetailsParams = new JSONObject();
//        // 8位银行识别码
//        accountDetailsParams.put("bankIdCode", "1*****");
//        // 24位伊班数字
//        accountDetailsParams.put("iBanNum", "567********");
//        // 服务数量, 服务金额
//        accountDetailsParams.put("serviceAmount", "200.00");
//        // 日期格式:YYYYDDMM
//        accountDetailsParams.put("valueDate", "20203112");
//
//        List<JSONObject> list = new ArrayList<>();
//        list.add(accountDetailsParams);
//        // 条件如果商人选择未来支付。 分开付款细节。
//        requestParams.put("accountDetails", list);

        List<JSONObject> requestEncryptAES = new ArrayList<>();
        requestEncryptAES.add(requestParams);
        String encryptAES = ARBUtil.encryptAES(key, JSONObject.toJSONString(requestEncryptAES));

        jsonObject.put("trandata", encryptAES);

        // 请求数据
        List<JSONObject> requestBody = new ArrayList<>();
        requestBody.add(jsonObject);

        Map<String, String> map = new HashMap<>();
        map.put("content-type", "application/json");

        try {
            String responseParams = HttpsUtils.HttpsRequest(BANK_HOSTED_URL, "POST", JSONObject.toJSONString(requestBody), map);
            JSONArray jsonArray = JSONObject.parseArray(responseParams);
            JSONObject object = (JSONObject) jsonArray.get(0);
            String status = object.getString("status");
            if ("1".equals(status)) {
                String result = object.getString("result");
                String[] split = result.split(":");
                String requestUrl = split[1] + ":" + split[2] + "?PaymentID=" + split[0];
                return CommonResult.success("SUCCESS", requestUrl);
            }
            return CommonResult.failMessage(500, "FAIL", object);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return CommonResult.fail(500, "FAIL");
    }

    @Override
    public CommonResult callback(HttpServletRequest request) {
//        //获取所有参数的map集合
//        Map<String, String[]> parameterMap = request.getParameterMap();
//        //遍历
//        Set<String> keySet = parameterMap.keySet();
//        for (String name : keySet) {
//            //根据键获取值
//            String[] values = parameterMap.get(name);
//            System.out.println(name);
//            for (String value : values) {
//                System.out.println(value);
//            }
//            System.out.println("------------");
//        }
        String paymentid = request.getParameter("paymentid");
        String trackid = request.getParameter("trackid");
        String custid = request.getParameter("custid");
        String trandata = request.getParameter("trandata");
        // 参数解密
        String decryptAES = ARBUtil.decryptAES(key, trandata);
        try {
            decryptAES = URLDecoder.decode(decryptAES, "UTF-8");
            log.info("解密后的数据: {}", decryptAES);
            JSONArray jsonArray = JSONObject.parseArray(decryptAES);
            JSONObject jsonObject = (JSONObject) jsonArray.get(0);
            if ("CAPTURED".equals(jsonObject.getString("result"))) {
                // transId 退款ID
                return CommonResult.success("SUCCESS", jsonObject.getString("transId"));
            }
            if (jsonObject.getString("result") != null) {
                return CommonResult.failMessage(500, "FAIL", jsonObject.getString("result"));
            } else {
                return CommonResult.failMessage(500, "FAIL", jsonObject.getString("errorText"));
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return CommonResult.fail(500, "FAIL");
    }

    @Override
    public CommonResult arbRefund(String amount, String refundOrderNo) {
        JSONObject jsonObject = new JSONObject();
        // 跨门户ID。商家下载相同的商家门户网站
        jsonObject.put("id", tranportalId);


        JSONObject requestParams = new JSONObject();
        // 跨门户ID。商家下载相同的商家门户网站
        requestParams.put("id", tranportalId);
        // Tranportal密码。在商家门户下载相同的商家。
        requestParams.put("password", password);
        // 定义事务操作 采购:1 退款:2 无效:3 调查:8
        requestParams.put("action", "2");
        // 交易金额
        requestParams.put("amt", amount);
        // KSA的3位货币代码例:682
        requestParams.put("currencyCode", "682");
        // 退款transId支付成功后返回的数据
        requestParams.put("transId", refundOrderNo);

        List<JSONObject> requestEncryptAES = new ArrayList<>();
        requestEncryptAES.add(requestParams);
        String encryptAES = ARBUtil.encryptAES(key, JSONObject.toJSONString(requestEncryptAES));

        jsonObject.put("trandata", encryptAES);

        // 请求数据
        List<JSONObject> requestBody = new ArrayList<>();
        requestBody.add(jsonObject);

        Map<String, String> map = new HashMap<>();
        map.put("content-type", "application/json");

        try {
            String responseParams = HttpsUtils.HttpsRequest(MERCHANT_HOSTED_URL, "POST", JSONObject.toJSONString(requestBody), map);
            JSONArray jsonArray = JSONObject.parseArray(responseParams);
            JSONObject object = (JSONObject) jsonArray.get(0);
            String status = object.getString("status");
            if ("1".equals(status)) {
                // 参数解密
                String decryptAES = ARBUtil.decryptAES(key, object.getString("trandata"));
                decryptAES = URLDecoder.decode(decryptAES, "UTF-8");
                log.info("解密后的数据: {}", decryptAES);
                return CommonResult.success("SUCCESS", object);
            }
            return CommonResult.failMessage(500, "FAIL", object);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return CommonResult.fail(500, "FAIL");
    }
}
